﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Net;
using System.Net.Sockets;


namespace ZY
{

    /// <summary>
    /// 发送数据的代理
    /// </summary>
    /// <param name="socketAsync"></param>
    public delegate void ConnectionFilter(SocketAsyncEventArgs socketAsync);

    /// <summary>
    /// 数据包输入代理
    /// </summary>
    /// <param name="data">输入包</param>
    /// <param name="socketAsync">socket Async 对象</param>
    public delegate void BinaryInputHandler(byte[] data, SocketAsyncEventArgs socketAsync);

    /// <summary>
    /// 异常错误通常是用户断开的代理
    /// </summary>
    /// <param name="message">消息</param>
    /// <param name="socketAsync"></param>
    /// <param name="erorr">错误代码</param>
    public delegate void MessageInputHandler(string message, SocketAsyncEventArgs socketAsync, int erorr);


    public class ZYServer : IDisposable
    {

        /// <summary>
        /// 用来确定是否以释放
        /// </summary>
        private bool isDisposed;

        /// <summary>
        /// SOCKET 服务器对象
        /// </summary>
        private Socket sock;

        /// <summary>
        /// 连接传入所处理的函数代理
        /// </summary>
        private EventHandler<SocketAsyncEventArgs> AcceptAsyCompleted { get; set; }

        /// <summary>
        /// 读取客户端数据的函数代理
        /// </summary>
        private EventHandler<SocketAsyncEventArgs> ReceiveCompleted { get; set; }

        /// <summary>
        /// 发送数据的函数代理
        /// </summary>
        private EventHandler<SocketAsyncEventArgs> SendCompleted { get; set; }
        /// <summary>
        /// 断开客户端处理的函数代理
        /// </summary>
        private EventHandler<SocketAsyncEventArgs> DisconnectCompleted { get; set; }




        /// <summary>
        /// 连接传入处理
        /// </summary>
        public ConnectionFilter Connetions { get; set; }

        /// <summary>
        /// 数据输入处理
        /// </summary>
        public BinaryInputHandler BinaryInput { get; set; }

        /// <summary>
        /// 异常错误通常是用户断开处理
        /// </summary>
        public MessageInputHandler MessageInput { get; set; }



        /// <summary>
        /// SocketAsyncEventArgs 列队
        /// </summary>
        private Queue<SocketAsyncEventArgs> AysncQueue;


        /// <summary>
        /// 保存SOCKET 客户连接列表
        /// </summary>
        private List<Socket> clientlist;

        /// <summary>
        /// 返回客户SOCKET 列表
        /// </summary>
        public List<Socket> Clientlist
        {
            get
            {

                return clientlist;
            }

        }

        ~ZYServer()
        {
            this.Dispose(false);

        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!isDisposed)
            {


                isDisposed = true;

                for (int i = 0; i < ListCout; i++)
                {
                    if (AysncQueue.Count > 0)
                    {
                        SocketAsyncEventArgs e = AysncQueue.Dequeue();
                        e.Dispose();

                    }
                    else
                    {
                        break;
                    }

                }



                foreach (Socket socks in clientlist)
                {
                    if (socks != null)
                    {
                        try
                        {
                            socks.Disconnect(false);
                        }
                        catch (SocketException)
                        {
                        }
                        catch (ObjectDisposedException)
                        {

                        }

                    }

                }

                if (sock != null)
                    sock.Close();


                if (disposing)
                {
                    clientlist.Clear();
                    AysncQueue.Clear();
                }

            }


        }



        /// <summary>
        /// 服务器SOCKET 对象
        /// </summary>
        public Socket Sock
        {
            get
            {
                return sock;
            }

        }

        /// <summary>
        /// 是否开启SOCKET Delay算法
        /// </summary>
        public bool NoDelay
        {
            get
            {
                return sock.NoDelay;
            }

            set
            {
                sock.NoDelay = value;
            }

        }

        /// <summary>
        /// SOCKET 的  ReceiveTimeout属性
        /// </summary>
        public int ReceiveTimeout
        {
            get
            {
                return sock.ReceiveTimeout;
            }

            set
            {
                sock.ReceiveTimeout = value;

            }


        }

        /// <summary>
        /// SOCKET 的 SendTimeout
        /// </summary>
        public int SendTimeout
        {
            get
            {
                return sock.SendTimeout;
            }

            set
            {
                sock.SendTimeout = value;
            }

        }

        /// <summary>
        /// SOCKET 的 UseOnlyOverlappedIO
        /// </summary>
        public bool UseOnlyOverlappedIO
        {
            get
            {
                return sock.UseOnlyOverlappedIO;
            }

            set
            {
                sock.UseOnlyOverlappedIO = value;
            }


        }




        /// <summary>
        /// 接收包大小
        /// </summary>
        public int MaxByteCout { get; set; }

        /// <summary>
        /// 最大用户连接
        /// </summary>
        private int ListCout;



        /// <summary>
        /// 建立一个新的ZYSERVER
        /// </summary>
        /// <param name="host">IP地址</param>
        /// <param name="port">服务端口</param>
        /// <param name="listcout">最大用户</param>
        public ZYServer(string host, int port, int listcout)
        {

            if (isDisposed == true)
            {
                throw new ObjectDisposedException("ZYServer is Disposed");
            }

            this.AysncQueue = new Queue<SocketAsyncEventArgs>(listcout);
            this.clientlist = new List<Socket>(listcout);

            this.ListCout = listcout;

            for (int i = 0; i < ListCout; i++)
            {
                SocketAsyncEventArgs e = new SocketAsyncEventArgs();
                AysncQueue.Enqueue(e);

            }


            AcceptAsyCompleted = new EventHandler<SocketAsyncEventArgs>(AcceptAsy_Completed);
            ReceiveCompleted = new EventHandler<SocketAsyncEventArgs>(Receive_Completed);
            SendCompleted = new EventHandler<SocketAsyncEventArgs>(Send_Completed);
            DisconnectCompleted = new EventHandler<SocketAsyncEventArgs>(Disconnect_Completed);


            sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);

            IPEndPoint myEnd = (String.IsNullOrEmpty(host)) ? (new IPEndPoint(Dns.GetHostEntry(Dns.GetHostName()).AddressList[0], port)) : (new IPEndPoint(IPAddress.Parse(host), port));

            sock.Bind(myEnd);

            sock.Listen(20);

            SendTimeout = 1000;

            ReceiveTimeout = 1000;

            UseOnlyOverlappedIO = true;

            MaxByteCout = 1024;

            SetAcceptAsy();



        }

        /// <summary>
        /// 设置一个 SocketAsyncEventArgs 对象用于监听
        /// </summary>
        private void SetAcceptAsy()
        {

            if (AysncQueue.Count > 0 && clientlist.Count < ListCout)
            {
                SocketAsyncEventArgs AcceptAsy = AysncQueue.Dequeue();

                AcceptAsy.Completed += AcceptAsyCompleted;

                Sock.AcceptAsync(AcceptAsy);

            }


        }



        void AcceptAsy_Completed(object sender, SocketAsyncEventArgs e)
        {

            if (!isDisposed)
            {



                Socket client = e.AcceptSocket;
                e.Completed -= AcceptAsy_Completed;
                e.Completed += ReceiveCompleted;
                byte[] buff = new byte[MaxByteCout];
                e.SetBuffer(buff, 0, buff.Length);
                client.ReceiveAsync(e);


                if (!clientlist.Contains(client))
                {
                    this.clientlist.Add(client);
                }
                else
                {
                    CloseSocket(e);
                }

                if (Connetions != null)
                {
                    Connetions(e);
                }

                SetAcceptAsy();
            }
            else
            {
                e.Dispose();
            }


        }


        void Receive_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket client = sender as Socket;


            if (e.BytesTransferred == 0) //检查获取的数据包长度 判断是否断开连接
            {
                if (MessageInput != null)  //如果断开 将调用断开代理
                {
                    string RemoteAddress = client.RemoteEndPoint.ToString();

                    MessageInput(RemoteAddress + " Disconnect", e, 1);

                }
                e.Completed -= ReceiveCompleted; // 一些善后工作
                clientlist.Remove(client);
                client.Close();
                e.Dispose();

                if (AysncQueue.Count < 10)  //如果 SocketAsyncEventArgs 列队数量==1 的时候 将重新创建 SocketAsyncEventArgs 列队 列队
                {
                    LocalAsyncQueue();
                }
            }
            else
            {
                if (BinaryInput != null)  //如果数据包获取代理不为空 将数据包传入代理
                {
                    byte[] data = new byte[e.BytesTransferred];

                    Array.Copy(e.Buffer, 0, data, 0, data.Length); //复制数据包

                    BinaryInput(data, e);

                }

                try
                {
                    if (client.Connected)
                        client.ReceiveAsync(e);  //重新监听数据包
                }
                catch (ObjectDisposedException)
                {
                }
            }


        }



        /// <summary>
        /// 断开一个用户SocketAsyncEventArgs对象
        /// </summary>
        /// <param name="e"></param>
        public void CloseSocket(SocketAsyncEventArgs e)
        {
            if (e.AcceptSocket != null)
            {
                if (AysncQueue.Count > 0)  //检测SocketAsyncEventArgs列队 并完成 异步断开
                {
                    SocketAsyncEventArgs me = this.AysncQueue.Dequeue();
                    me.Completed += DisconnectCompleted;
                    e.AcceptSocket.DisconnectAsync(me);

                }
                else
                {
                    LocalAsyncQueue();

                    SocketAsyncEventArgs me = this.AysncQueue.Dequeue();
                    me.Completed += DisconnectCompleted;
                    e.AcceptSocket.DisconnectAsync(me);
                }

                if (MessageInput != null)
                {
                    string RemoteAddress = e.AcceptSocket.RemoteEndPoint.ToString(); //将断开信息传入 MessageInput代理

                    MessageInput(RemoteAddress + " Disconnect", e, 1);

                }


            }



        }




        void Disconnect_Completed(object sender, SocketAsyncEventArgs e)
        {
            Socket client = sender as Socket;

            clientlist.Remove(client);

            e.Completed -= ReceiveCompleted;
            e.Dispose();

            if (AysncQueue.Count<10)
            {
                LocalAsyncQueue();
            }

        }

        /// <summary>
        /// 发送数据包
        /// </summary>
        /// <param name="sock">目标Socket</param>
        /// <param name="data">数据</param>
        public void SendData(Socket sock, byte[] data)
        {

            if (sock.Connected)
            {
                SocketAsyncEventArgs e = new SocketAsyncEventArgs(); //创建一个 SocketAsyncEventArgs 对象用于发送 数据包
                e.Completed += new EventHandler<SocketAsyncEventArgs>(SendCompleted);
                e.SetBuffer(data, 0, data.Length);
                sock.SendAsync(e);

            }
            else
            {
                throw new ObjectDisposedException("Not Send Data Socket Disconnect");
            }

        }

        void Send_Completed(object sender, SocketAsyncEventArgs e)
        {
            try
            {
                if (e.BytesTransferred < e.Buffer.Length) //如果 发送的数据包数量小于 数据包长度将重新发送
                {
                    Socket Socks = sender as Socket;

                    if (Socks != null)
                    {
                        Socks.SendAsync(e);
                    }
                    else
                    {
                        e.Dispose();
                    }
                }

            }
            catch (ObjectDisposedException)
            {
                if (MessageInput != null)
                {
                    MessageInput.Invoke("无法发送数据,Socket对象已经断开连接", e, 1);
                }
                // MessageInput("无法发送数据,Socket对象已经断开连接", e);
            }
            finally
            {
                e.Dispose();
            }

        }


        /// <summary>
        /// 重组 SocketAsyncEventArgs 列队
        /// </summary>
        void LocalAsyncQueue()
        {
            for (int i = 0; i < ListCout; i++)
            {
                SocketAsyncEventArgs e = new SocketAsyncEventArgs();
                AysncQueue.Enqueue(e);

            }
        }








    }
}
